package com.symaster.gameengine.core;

/**
 * 渲染器顶级父类
 *
 * @author yinmiao
 * @version 2023/11/15
 */
public abstract class Renderer extends FboComponent {

    /**
     * 是否为静态渲染器
     */
    private boolean staticRenderer = true;
    /**
     * 是否渲染
     */
    private boolean visible = true;

    /**
     * @return 当前组件是否渲染
     */
    public boolean isVisible() {
        return visible;
    }

    /**
     * 设置当前组件是否渲染
     *
     * @param visible 是否渲染
     */
    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    /**
     * @return 返回当前状态, 是否为静态渲染器
     */
    public boolean isStaticRenderer() {
        return staticRenderer;
    }

    /**
     * 设置当前渲染器状态是否为静态渲染器
     * <p>如果是静态渲染器, 则只会渲染一次, 不会每帧刷新Fbo</p>
     *
     * @param staticRenderer 是否为静态渲染器
     */
    public void setStaticRenderer(boolean staticRenderer) {
        this.staticRenderer = staticRenderer;
    }

    @Override
    public void repaint2Fbo() {
        if (setupFBO(getWidth(), getHeight()) || !staticRenderer || isUpdate()) {
            // 绑定到当前Fbo缓冲区
            bindFbo();
            // 清空
            clear();
            // 绘制
            draw();
            // 取消绑定
            bindDefaultBuffer();
        }
    }

    /**
     * @return 返回当前帧是否需要刷新Fbo, 此处返回true则肯定会刷新fbo, 返回false不一定不会刷新fbo
     * @see #repaint2Fbo()
     */
    protected boolean isUpdate() {
        return false;
    }

    /**
     * @return 当前渲染器需要框架分配的显示的大小
     */
    public abstract int getWidth();

    /**
     * @return 当前渲染器需要框架分配的显示的大小
     */
    public abstract int getHeight();

    /**
     * 子组件使用, 在当前Fbo缓冲区里面绘制
     */
    protected abstract void draw();

    /**
     * @return 返回这个渲染器的镜像
     */
    public Renderer mirror() {
        Renderer renderer = this;

        return new Renderer() {
            private final Renderer srcRenderer = renderer;

            @Override
            public boolean isStaticRenderer() {
                return srcRenderer.isStaticRenderer();
            }

            @Override
            public void setStaticRenderer(boolean staticRenderer) {
                srcRenderer.setStaticRenderer(staticRenderer);
            }

            @Override
            public void repaint2Fbo() {
                srcRenderer.repaint2Fbo();
            }

            @Override
            public Renderer mirror() {
                return srcRenderer.mirror();
            }

            @Override
            public int getWidth() {
                return srcRenderer.getWidth();
            }

            @Override
            public int getHeight() {
                return srcRenderer.getHeight();
            }

            @Override
            protected void draw() {
                srcRenderer.draw();
            }

            @Override
            public boolean setupFBO(int fboWidth, int fboHeight) {
                return srcRenderer.setupFBO(fboWidth, fboHeight);
            }

            @Override
            public void bindDefaultBuffer() {
                srcRenderer.bindDefaultBuffer();
            }

            @Override
            public void bindFbo() {
                srcRenderer.bindFbo();
            }

            @Override
            public void bindTexture() {
                srcRenderer.bindTexture();
            }

            @Override
            public int getFboWidth() {
                return srcRenderer.getFboWidth();
            }

            @Override
            public int getFboHeight() {
                return srcRenderer.getFboHeight();
            }

            @Override
            public int getFbo() {
                return srcRenderer.getFbo();
            }

            @Override
            public int getFboTexture() {
                return srcRenderer.getFboTexture();
            }

            @Override
            public void fboRenderScene() {
                srcRenderer.fboRenderScene();
            }

            @Override
            public void renderTextureToScreen() {
                srcRenderer.renderTextureToScreen();
            }

            @Override
            public void clear() {
                srcRenderer.clear();
            }

            @Override
            public void resourceLoad() {
                srcRenderer.resourceLoad();
            }
        };
    }
}
